package mips.instructions;

import java.util.HashMap;

import mips.instructions.cop0.COP0;
import mips.instructions.cop0.ERET;
import mips.instructions.cop0.MFC0;
import mips.instructions.cop0.MTC0;
import mips.instructions.cop0.TLBP;
import mips.instructions.cop0.TLBR;
import mips.instructions.cop0.TLBWI;
import mips.instructions.cop0.TLBWR;
import mips.instructions.fpu.BC1;
import mips.instructions.fpu.BC1F;
import mips.instructions.fpu.BC1FL;
import mips.instructions.fpu.BC1T;
import mips.instructions.fpu.BC1TL;
import mips.instructions.fpu.CFC1;
import mips.instructions.fpu.COP1;
import mips.instructions.fpu.COP1D;
import mips.instructions.fpu.COP1L;
import mips.instructions.fpu.COP1S;
import mips.instructions.fpu.COP1W;
import mips.instructions.fpu.CTC1;
import mips.instructions.fpu.DMFC1;
import mips.instructions.fpu.DMTC1;
import mips.instructions.fpu.MFC1;
import mips.instructions.fpu.MTC1;


/**
 * This class is the base of all MIPS instruction implementations.<br/><br/>
 * Contained within are helper methods to do useful operations such as<br/>
 * sign-extension and zero-extension, along with definitions of the methods
 * shared by all concrete subclasses including execute(...), emit(...) and
 * the various overloaded versions of getName(...).
 *  
 * @author jnmartin84@gmail.com
 */
public abstract class Instruction {

	private static final HashMap<Integer, Instruction> BC1_MAP;
	private static final HashMap<Integer, Instruction> COP0_MAP;
	private static final HashMap<Integer, Instruction> COP1_MAP;
	private static final HashMap<Integer, Instruction> COP1_D_MAP;
	private static final HashMap<Integer, Instruction> COP1_L_MAP;
	private static final HashMap<Integer, Instruction> COP1_S_MAP;
	private static final HashMap<Integer, Instruction> COP1_W_MAP;
	private static final HashMap<Integer, Instruction> OPCODE_MAP;
	private static final HashMap<Integer, Instruction> REGIMM_MAP;
	private static final HashMap<Integer, Instruction> SPECIAL_MAP;
	private static final HashMap<Integer, Instruction> TLB_MAP;

	/**
	 * Set up all of the opcode/function maps.
	 */
	static {

		BC1_MAP = new HashMap<Integer, Instruction>();
		COP0_MAP = new HashMap<Integer, Instruction>();
		COP1_MAP = new HashMap<Integer, Instruction>();
		COP1_D_MAP = new HashMap<Integer, Instruction>();
		COP1_L_MAP = new HashMap<Integer, Instruction>();
		COP1_S_MAP = new HashMap<Integer, Instruction>();
		COP1_W_MAP = new HashMap<Integer, Instruction>();
		OPCODE_MAP = new HashMap<Integer, Instruction>();
		REGIMM_MAP = new HashMap<Integer, Instruction>();
		SPECIAL_MAP = new HashMap<Integer, Instruction>();
		TLB_MAP = new HashMap<Integer, Instruction>();

		initBc1Map();
		initCop0Map();
		initCop1Map();
		initCop1DMap();
		initCop1LMap();
		initCop1SMap();
		initCop1WMap();
		initOpcodeMap();
		initRegimmMap();
		initSpecialMap();
		initTlbMap();
	}

	public static int IMMED;
	public static int RD;
	public static int RS;
	public static int RT;
	public static long TMP;
	
	/**
	 * Wanted this to be private but subclasses need it visible.
	 */
	protected Instruction(){}
	
	/**
			CPU: Instructions encoded by opcode field.
		    31---------26---------------------------------------------------0
		    |  opcode   |                                                   |
		    ------6----------------------------------------------------------
		    |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo
		000 | *1    | *2    | J     | JAL   | BEQ   | BNE   | BLEZ  | BGTZ  |
		001 | ADDI  | ADDIU | SLTI  | SLTIU | ANDI  | ORI   | XORI  | LUI   |
		010 | *3    | *4    |  ---  |  ---  | BEQL  | BNEL  | BLEZL | BGTZL |
		011 | DADDI |DADDIU | LDL   | LDR   |  ---  |  ---  |  ---  |  ---  |
		100 | LB    | LH    | LWL   | LW    | LBU   | LHU   | LWR   | LWU   |
		101 | SB    | SH    | SWL   | SW    | SDL   | SDR   | SWR   | CACHE |
		110 | LL    | LWC1  |  ---  |  ---  | LLD   | LDC1  | LDC2  | LD    |
		111 | SC    | SWC1  |  ---  |  ---  | SCD   | SDC1  | SDC2  | SD    |
		 hi |-------|-------|-------|-------|-------|-------|-------|-------|
		     *1 = SPECIAL, see SPECIAL list    *2 = REGIMM, see REGIMM list
		     *3 = COP0                         *4 = COP1
	*/
	private static final void initOpcodeMap() {

		OPCODE_MAP.put( 0, SPECIAL.getInstance());
		OPCODE_MAP.put( 1, REGIMM.getInstance());
		OPCODE_MAP.put( 2, J.getInstance());
		OPCODE_MAP.put( 3, JAL.getInstance());
		OPCODE_MAP.put( 4, BEQ.getInstance());
		OPCODE_MAP.put( 5, BNE.getInstance());
		OPCODE_MAP.put( 6, BLEZ.getInstance());
		OPCODE_MAP.put( 7, BGTZ.getInstance());
		
		OPCODE_MAP.put( 8, ADDI.getInstance());
		OPCODE_MAP.put( 9, ADDIU.getInstance());
		OPCODE_MAP.put(10, SLTI.getInstance());
		OPCODE_MAP.put(11, SLTIU.getInstance());
		OPCODE_MAP.put(12, ANDI.getInstance());
		OPCODE_MAP.put(13, ORI.getInstance());
		OPCODE_MAP.put(14, XORI.getInstance());
		OPCODE_MAP.put(15, LUI.getInstance());
		
		OPCODE_MAP.put(16, COP0.getInstance());
		OPCODE_MAP.put(17, COP1.getInstance());
		OPCODE_MAP.put(18, UNHANDLED.getInstance());
		OPCODE_MAP.put(19, UNHANDLED.getInstance());
		OPCODE_MAP.put(20, BEQL.getInstance());
		OPCODE_MAP.put(21, BNEL.getInstance());
		OPCODE_MAP.put(22, BLEZL.getInstance());
		OPCODE_MAP.put(23, BGTZL.getInstance());
		
		OPCODE_MAP.put(24, DADDI.getInstance());
		OPCODE_MAP.put(25, DADDIU.getInstance());
		OPCODE_MAP.put(26, LDL.getInstance());
		OPCODE_MAP.put(27, LDR.getInstance());
		OPCODE_MAP.put(28, UNHANDLED.getInstance());
		OPCODE_MAP.put(29, UNHANDLED.getInstance());
		OPCODE_MAP.put(30, UNHANDLED.getInstance());
		OPCODE_MAP.put(31, UNHANDLED.getInstance());
		
		OPCODE_MAP.put(32, LB.getInstance());
		OPCODE_MAP.put(33, LH.getInstance());
		OPCODE_MAP.put(34, LWL.getInstance());
		OPCODE_MAP.put(35, LW.getInstance());
		OPCODE_MAP.put(36, LBU.getInstance());
		OPCODE_MAP.put(37, LHU.getInstance());
		OPCODE_MAP.put(38, LWR.getInstance());
		OPCODE_MAP.put(39, LWU.getInstance());
		
		OPCODE_MAP.put(40, SB.getInstance());
		OPCODE_MAP.put(41, SH.getInstance());
		OPCODE_MAP.put(42, SWL.getInstance());
		OPCODE_MAP.put(43, SW.getInstance());
		OPCODE_MAP.put(44, SDL.getInstance());
		OPCODE_MAP.put(45, SDR.getInstance());
		OPCODE_MAP.put(46, SWR.getInstance());
		OPCODE_MAP.put(47, CACHE.getInstance());
		
		OPCODE_MAP.put(48, LL.getInstance());
		OPCODE_MAP.put(49, LWC1.getInstance());
		OPCODE_MAP.put(50, LWC2.getInstance());
		OPCODE_MAP.put(51, UNHANDLED.getInstance());
		OPCODE_MAP.put(52, LLD.getInstance());
		OPCODE_MAP.put(53, LDC1.getInstance());
		OPCODE_MAP.put(54, LDC2.getInstance());
		OPCODE_MAP.put(55, LD.getInstance());
		
		OPCODE_MAP.put(56, SC.getInstance());
		OPCODE_MAP.put(57, SWC1.getInstance());
		OPCODE_MAP.put(58, SWC2.getInstance());
		OPCODE_MAP.put(59, UNHANDLED.getInstance());
		OPCODE_MAP.put(60, SCD.getInstance());
		OPCODE_MAP.put(61, SDC1.getInstance());
		OPCODE_MAP.put(62, SDC2.getInstance());
		OPCODE_MAP.put(63, SD.getInstance());
	}

	/**
		    SPECIAL: Instr. encoded by function field when opcode field = SPECIAL.
		    31---------26------------------------------------------5--------0
		    | = SPECIAL |                                         | function|
		    ------6----------------------------------------------------6-----
		    |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo
		000 | SLL   |  ---  | SRL   | SRA   | SLLV  |  ---  | SRLV  | SRAV  |
		001 | JR    | JALR  |  ---  |  ---  |SYSCALL| BREAK |  ---  | SYNC  |
		010 | MFHI  | MTHI  | MFLO  | MTLO  | DSLLV |  ---  | DSRLV | DSRAV |
		011 | MULT  | MULTU | DIV   | DIVU  | DMULT | DMULTU| DDIV  | DDIVU |
		100 | ADD   | ADDU  | SUB   | SUBU  | AND   | OR    | XOR   | NOR   |
		101 |  ---  |  ---  | SLT   | SLTU  | DADD  | DADDU | DSUB  | DSUBU |
		110 | TGE   | TGEU  | TLT   | TLTU  | TEQ   |  ---  | TNE   |  ---  |
		111 | DSLL  |  ---  | DSRL  | DSRA  |DSLL32 |  ---  |DSRL32 |DSRA32 |
		 hi |-------|-------|-------|-------|-------|-------|-------|-------|
	*/
	private static final void initSpecialMap() {

		SPECIAL_MAP.put( 0, SLL.getInstance());
		SPECIAL_MAP.put( 1, UNHANDLED.getInstance());
		SPECIAL_MAP.put( 2, SRL.getInstance());
		SPECIAL_MAP.put( 3, SRA.getInstance());
		SPECIAL_MAP.put( 4, SLLV.getInstance());
		SPECIAL_MAP.put( 5, UNHANDLED.getInstance());
		SPECIAL_MAP.put( 6, SRLV.getInstance());
		SPECIAL_MAP.put( 7, SRAV.getInstance());
		
		SPECIAL_MAP.put( 8, JR.getInstance());
		SPECIAL_MAP.put( 9, JALR.getInstance());
		SPECIAL_MAP.put(10, UNHANDLED.getInstance());
		SPECIAL_MAP.put(11, UNHANDLED.getInstance());
		SPECIAL_MAP.put(12, SYSCALL.getInstance());
		SPECIAL_MAP.put(13, BREAK.getInstance());
		SPECIAL_MAP.put(14, UNHANDLED.getInstance());
		SPECIAL_MAP.put(15, SYNC.getInstance());
		
		SPECIAL_MAP.put(16, MFHI.getInstance());
		SPECIAL_MAP.put(17, MTHI.getInstance());
		SPECIAL_MAP.put(18, MFLO.getInstance());
		SPECIAL_MAP.put(19, MTLO.getInstance());
		SPECIAL_MAP.put(20, DSLLV.getInstance());
		SPECIAL_MAP.put(21, UNHANDLED.getInstance());
		SPECIAL_MAP.put(22, DSRLV.getInstance());
		SPECIAL_MAP.put(23, DSRAV.getInstance());
		
		SPECIAL_MAP.put(24, MULT.getInstance());
		SPECIAL_MAP.put(25, MULTU.getInstance());
		SPECIAL_MAP.put(26, DIV.getInstance());
		SPECIAL_MAP.put(27, DIVU.getInstance());
		SPECIAL_MAP.put(28, DMULT.getInstance());
		SPECIAL_MAP.put(29, DMULTU.getInstance());
		SPECIAL_MAP.put(30, DDIV.getInstance());
		SPECIAL_MAP.put(31, DDIVU.getInstance());
		
		SPECIAL_MAP.put(32, ADD.getInstance());
		SPECIAL_MAP.put(33, ADDU.getInstance());
		SPECIAL_MAP.put(34, SUB.getInstance());
		SPECIAL_MAP.put(35, SUBU.getInstance());
		SPECIAL_MAP.put(36, AND.getInstance());
		SPECIAL_MAP.put(37, OR.getInstance());
		SPECIAL_MAP.put(38, XOR.getInstance());
		SPECIAL_MAP.put(39, NOR.getInstance());
		
		SPECIAL_MAP.put(40, UNHANDLED.getInstance());
		SPECIAL_MAP.put(41, UNHANDLED.getInstance());
		SPECIAL_MAP.put(42, SLT.getInstance());
		SPECIAL_MAP.put(43, SLTU.getInstance());
		SPECIAL_MAP.put(44, DADD.getInstance());
		SPECIAL_MAP.put(45, DADDU.getInstance());
		SPECIAL_MAP.put(46, DSUB.getInstance());
		SPECIAL_MAP.put(47, DSUBU.getInstance());
		
		SPECIAL_MAP.put(48, TGE.getInstance());
		SPECIAL_MAP.put(49, TGEU.getInstance());
		SPECIAL_MAP.put(50, TLT.getInstance());
		SPECIAL_MAP.put(51, TLTU.getInstance());
		SPECIAL_MAP.put(52, TEQ.getInstance());
		SPECIAL_MAP.put(53, UNHANDLED.getInstance());
		SPECIAL_MAP.put(54, TNE.getInstance());
		SPECIAL_MAP.put(55, UNHANDLED.getInstance());
		
		SPECIAL_MAP.put(56, DSLL.getInstance());
		SPECIAL_MAP.put(57, UNHANDLED.getInstance());
		SPECIAL_MAP.put(58, DSRL.getInstance());
		SPECIAL_MAP.put(59, DSRA.getInstance());
		SPECIAL_MAP.put(60, DSLL32.getInstance());
		SPECIAL_MAP.put(61, UNHANDLED.getInstance());
		SPECIAL_MAP.put(62, DSRL32.getInstance());
		SPECIAL_MAP.put(63, DSRA32.getInstance());
	}

	/**
		    REGIMM: Instructions encoded by the rt field when opcode field = REGIMM.
		    31---------26----------20-------16------------------------------0
		    | = REGIMM  |          |   rt    |                              |
		    ------6---------------------5------------------------------------
		    |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo
		 00 | BLTZ  | BGEZ  | BLTZL | BGEZL |  ---  |  ---  |  ---  |  ---  |
		 01 | TGEI  | TGEIU | TLTI  | TLTIU | TEQI  |  ---  | TNEI  |  ---  |
		 10 | BLTZAL| BGEZAL|BLTZALL|BGEZALL|  ---  |  ---  |  ---  |  ---  |
		 11 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		 hi |-------|-------|-------|-------|-------|-------|-------|-------|
	*/
	private static final void initRegimmMap() {

		REGIMM_MAP.put( 0, BLTZ.getInstance());
		REGIMM_MAP.put( 1, BGEZ.getInstance());
		REGIMM_MAP.put( 2, BLTZL.getInstance());
		REGIMM_MAP.put( 3, BGEZL.getInstance());
		REGIMM_MAP.put( 4, UNHANDLED.getInstance());
		REGIMM_MAP.put( 5, UNHANDLED.getInstance());
		REGIMM_MAP.put( 6, UNHANDLED.getInstance());
		REGIMM_MAP.put( 7, UNHANDLED.getInstance());
		
		REGIMM_MAP.put( 8, TGEI.getInstance());
		REGIMM_MAP.put( 9, TGEIU.getInstance());
		REGIMM_MAP.put(10, TLTI.getInstance());
		REGIMM_MAP.put(11, TLTIU.getInstance());
		REGIMM_MAP.put(12, TEQI.getInstance());
		REGIMM_MAP.put(13, UNHANDLED.getInstance());
		REGIMM_MAP.put(14, TNEI.getInstance());
		REGIMM_MAP.put(15, UNHANDLED.getInstance());
		
		REGIMM_MAP.put(16, BLTZAL.getInstance());
		REGIMM_MAP.put(17, BGEZAL.getInstance());
		REGIMM_MAP.put(18, BLTZALL.getInstance());
		REGIMM_MAP.put(19, BGEZALL.getInstance());
		REGIMM_MAP.put(20, UNHANDLED.getInstance());
		REGIMM_MAP.put(21, UNHANDLED.getInstance());
		REGIMM_MAP.put(22, UNHANDLED.getInstance());
		REGIMM_MAP.put(23, UNHANDLED.getInstance());
		
		REGIMM_MAP.put(24, UNHANDLED.getInstance());
		REGIMM_MAP.put(25, UNHANDLED.getInstance());
		REGIMM_MAP.put(26, UNHANDLED.getInstance());
		REGIMM_MAP.put(27, UNHANDLED.getInstance());
		REGIMM_MAP.put(28, UNHANDLED.getInstance());
		REGIMM_MAP.put(29, UNHANDLED.getInstance());
		REGIMM_MAP.put(30, UNHANDLED.getInstance());
		REGIMM_MAP.put(31, UNHANDLED.getInstance());
	}

	/**
		    COP0: Instructions encoded by the fmt field when opcode = COP0.
		    31--------26-25------21 ----------------------------------------0
		    |  = COP0   |   fmt   |                                         |
		    ------6----------5-----------------------------------------------
		    |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo
		 00 | MFC0  |  ---  |  ---  |  ---  | MTC0  |  ---  |  ---  |  ---  |
		 01 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		 10 | *1    |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		 11 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		 hi |-------|-------|-------|-------|-------|-------|-------|-------|
		     *1 = TLB instr, see TLB list
	*/
	private static final void initCop0Map() {
		
		COP0_MAP.put( 0, MFC0.getInstance());
		COP0_MAP.put( 1, UNHANDLED.getInstance());
		COP0_MAP.put( 2, UNHANDLED.getInstance());
		COP0_MAP.put( 3, UNHANDLED.getInstance());		
		COP0_MAP.put( 4, MTC0.getInstance());
		COP0_MAP.put( 5, UNHANDLED.getInstance());
		COP0_MAP.put( 6, UNHANDLED.getInstance());
		COP0_MAP.put( 7, UNHANDLED.getInstance());
		
		COP0_MAP.put( 8, UNHANDLED.getInstance());
		COP0_MAP.put( 9, UNHANDLED.getInstance());
		COP0_MAP.put(10, UNHANDLED.getInstance());
		COP0_MAP.put(11, UNHANDLED.getInstance());
		COP0_MAP.put(12, UNHANDLED.getInstance());		
		COP0_MAP.put(13, UNHANDLED.getInstance());
		COP0_MAP.put(14, UNHANDLED.getInstance());
		COP0_MAP.put(15, UNHANDLED.getInstance());
		
		COP0_MAP.put(16, TLB.getInstance());
		COP0_MAP.put(17, UNHANDLED.getInstance());
		COP0_MAP.put(18, UNHANDLED.getInstance());
		COP0_MAP.put(18, UNHANDLED.getInstance());
		COP0_MAP.put(20, UNHANDLED.getInstance());		
		COP0_MAP.put(21, UNHANDLED.getInstance());
		COP0_MAP.put(22, UNHANDLED.getInstance());
		COP0_MAP.put(23, UNHANDLED.getInstance());
		
		COP0_MAP.put(24, UNHANDLED.getInstance());		
		COP0_MAP.put(25, UNHANDLED.getInstance());
		COP0_MAP.put(26, UNHANDLED.getInstance());
		COP0_MAP.put(27, UNHANDLED.getInstance());
		COP0_MAP.put(28, UNHANDLED.getInstance());		
		COP0_MAP.put(29, UNHANDLED.getInstance());
		COP0_MAP.put(30, UNHANDLED.getInstance());
		COP0_MAP.put(31, UNHANDLED.getInstance());
	}
	
	/**
		    TLB: Instructions encoded by the function field when opcode
		         = COP0 and fmt = TLB.
		    31--------26-25------21 -------------------------------5--------0
		    |  = COP0   |  = TLB  |                               | function|
		    ------6----------5-----------------------------------------6-----
		    |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo
		000 |  ---  | TLBR  | TLBWI |  ---  |  ---  |  ---  | TLBWR |  ---  |
		001 | TLBP  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		010 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		011 | ERET  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		100 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		101 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		110 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		111 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		 hi |-------|-------|-------|-------|-------|-------|-------|-------|
	*/
	private static final void initTlbMap() {

		TLB_MAP.put( 0, UNHANDLED.getInstance());
		TLB_MAP.put( 1, TLBR.getInstance());
		TLB_MAP.put( 2, TLBWI.getInstance());
		TLB_MAP.put( 3, UNHANDLED.getInstance());
		TLB_MAP.put( 4, UNHANDLED.getInstance());
		TLB_MAP.put( 5, UNHANDLED.getInstance());
		TLB_MAP.put( 6, TLBWR.getInstance());
		TLB_MAP.put( 7, UNHANDLED.getInstance());

		TLB_MAP.put( 8, TLBP.getInstance());
		TLB_MAP.put( 9, UNHANDLED.getInstance());
		TLB_MAP.put(10, UNHANDLED.getInstance());
		TLB_MAP.put(11, UNHANDLED.getInstance());
		TLB_MAP.put(12, UNHANDLED.getInstance());
		TLB_MAP.put(13, UNHANDLED.getInstance());
		TLB_MAP.put(14, UNHANDLED.getInstance());
		TLB_MAP.put(15, UNHANDLED.getInstance());

		TLB_MAP.put(16, UNHANDLED.getInstance());
		TLB_MAP.put(17, UNHANDLED.getInstance());
		TLB_MAP.put(18, UNHANDLED.getInstance());
		TLB_MAP.put(19, UNHANDLED.getInstance());
		TLB_MAP.put(20, UNHANDLED.getInstance());
		TLB_MAP.put(21, UNHANDLED.getInstance());
		TLB_MAP.put(22, UNHANDLED.getInstance());
		TLB_MAP.put(23, UNHANDLED.getInstance());
		
		TLB_MAP.put(24, ERET.getInstance());
		TLB_MAP.put(25, UNHANDLED.getInstance());
		TLB_MAP.put(26, UNHANDLED.getInstance());
		TLB_MAP.put(27, UNHANDLED.getInstance());
		TLB_MAP.put(28, UNHANDLED.getInstance());
		TLB_MAP.put(29, UNHANDLED.getInstance());
		TLB_MAP.put(30, UNHANDLED.getInstance());
		TLB_MAP.put(31, UNHANDLED.getInstance());
		
		TLB_MAP.put(32, UNHANDLED.getInstance());
		TLB_MAP.put(33, UNHANDLED.getInstance());
		TLB_MAP.put(34, UNHANDLED.getInstance());
		TLB_MAP.put(35, UNHANDLED.getInstance());
		TLB_MAP.put(36, UNHANDLED.getInstance());
		TLB_MAP.put(37, UNHANDLED.getInstance());
		TLB_MAP.put(38, UNHANDLED.getInstance());
		TLB_MAP.put(39, UNHANDLED.getInstance());
		
		TLB_MAP.put(40, UNHANDLED.getInstance());
		TLB_MAP.put(41, UNHANDLED.getInstance());
		TLB_MAP.put(42, UNHANDLED.getInstance());
		TLB_MAP.put(43, UNHANDLED.getInstance());
		TLB_MAP.put(44, UNHANDLED.getInstance());
		TLB_MAP.put(45, UNHANDLED.getInstance());
		TLB_MAP.put(46, UNHANDLED.getInstance());
		TLB_MAP.put(47, UNHANDLED.getInstance());
		
		TLB_MAP.put(48, UNHANDLED.getInstance());
		TLB_MAP.put(49, UNHANDLED.getInstance());
		TLB_MAP.put(50, UNHANDLED.getInstance());
		TLB_MAP.put(51, UNHANDLED.getInstance());
		TLB_MAP.put(52, UNHANDLED.getInstance());
		TLB_MAP.put(53, UNHANDLED.getInstance());
		TLB_MAP.put(54, UNHANDLED.getInstance());
		TLB_MAP.put(55, UNHANDLED.getInstance());
		
		TLB_MAP.put(56, UNHANDLED.getInstance());
		TLB_MAP.put(57, UNHANDLED.getInstance());
		TLB_MAP.put(58, UNHANDLED.getInstance());
		TLB_MAP.put(59, UNHANDLED.getInstance());
		TLB_MAP.put(60, UNHANDLED.getInstance());
		TLB_MAP.put(61, UNHANDLED.getInstance());
		TLB_MAP.put(62, UNHANDLED.getInstance());
		TLB_MAP.put(63, UNHANDLED.getInstance());
	}
	

	/**
		    COP1: Instructions encoded by the fmt field when opcode = COP1.
		    31--------26-25------21 ----------------------------------------0
		    |  = COP1   |   fmt   |                                         |
		    ------6----------5-----------------------------------------------
		    |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo
		 00 | MFC1  | DMFC1 | CFC1  |  ---  | MTC1  | DMTC1 | CTC1  |  ---  |
		 01 | *1    |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		 10 | *2    | *3    |  ---  |  ---  | *4    | *5    |  ---  |  ---  |
		 11 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		 hi |-------|-------|-------|-------|-------|-------|-------|-------|
		     *1 = BC instructions, see BC1 list
		     *2 = S instr, see FPU list            *3 = D instr, see FPU list
		     *4 = W instr, see FPU list            *5 = L instr, see FPU list
	*/
	private static final void initCop1Map() {
		
		COP1_MAP.put( 0, MFC1.getInstance());
		COP1_MAP.put( 1, DMFC1.getInstance());
		COP1_MAP.put( 2, CFC1.getInstance());
		COP1_MAP.put( 3, UNHANDLED.getInstance());		
		COP1_MAP.put( 4, MTC1.getInstance());
		COP1_MAP.put( 5, DMTC1.getInstance());
		COP1_MAP.put( 6, CTC1.getInstance());
		COP1_MAP.put( 7, UNHANDLED.getInstance());
		
		COP1_MAP.put( 8, BC1.getInstance());
		COP1_MAP.put( 9, UNHANDLED.getInstance());
		COP1_MAP.put(10, UNHANDLED.getInstance());
		COP1_MAP.put(11, UNHANDLED.getInstance());
		COP1_MAP.put(12, UNHANDLED.getInstance());		
		COP1_MAP.put(13, UNHANDLED.getInstance());
		COP1_MAP.put(14, UNHANDLED.getInstance());
		COP1_MAP.put(15, UNHANDLED.getInstance());
		
		COP1_MAP.put(16, COP1S.getInstance());
		COP1_MAP.put(17, COP1D.getInstance());
		COP1_MAP.put(18, UNHANDLED.getInstance());
		COP1_MAP.put(19, UNHANDLED.getInstance());
		COP1_MAP.put(20, COP1W.getInstance());
		COP1_MAP.put(21, COP1L.getInstance());
		COP1_MAP.put(22, UNHANDLED.getInstance());
		COP1_MAP.put(23, UNHANDLED.getInstance());
		
		COP1_MAP.put(24, UNHANDLED.getInstance());
		COP1_MAP.put(25, UNHANDLED.getInstance());
		COP1_MAP.put(26, UNHANDLED.getInstance());
		COP1_MAP.put(27, UNHANDLED.getInstance());
		COP1_MAP.put(28, UNHANDLED.getInstance());
		COP1_MAP.put(29, UNHANDLED.getInstance());
		COP1_MAP.put(30, UNHANDLED.getInstance());
		COP1_MAP.put(31, UNHANDLED.getInstance());
	}

	/**
		    BC1: Instructions encoded by the nd and tf fields when opcode
		         = COP1 and fmt = BC
		    31--------26-25------21 ---17--16-------------------------------0
		    |  = COP1   |  = BC   |    |nd|tf|                              |
		    ------6----------5-----------1--1--------------------------------
		    |---0---|---1---| tf
		  0 | BC1F  | BC1T  |
		  1 | BC1FL | BC1TL |
		 nd |-------|-------|
	*/
	private static final void initBc1Map() {
	
		BC1_MAP.put(0, BC1F.getInstance());
		BC1_MAP.put(1, BC1T.getInstance());
		BC1_MAP.put(2, BC1FL.getInstance());
		BC1_MAP.put(3, BC1TL.getInstance());
	}
	
	/**
		    FPU: Instructions encoded by the function field when opcode = COP1
		         and fmt = S
		    31--------26-25------21 -------------------------------5--------0
		    |  = COP1   |  = S    |                               | function|
		    ------6----------5-----------------------------------------6-----
		    |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo
		000 | ADD   | SUB   | MUL   | DIV   | SQRT  | ABS   | MOV   | NEG   |
		001 |ROUND.L|TRUNC.L| CEIL.L|FLOOR.L|ROUND.W|TRUNC.W| CEIL.W|FLOOR.W|
		010 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		011 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		100 |  ---  | CVT.D |  ---  |  ---  | CVT.W | CVT.L |  ---  |  ---  |
		101 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		110 | C.F   | C.UN  | C.EQ  | C.UEQ | C.OLT | C.ULT | C.OLE | C.ULE |
		111 | C.SF  | C.NGLE| C.SEQ | C.NGL | C.LT  | C.NGE | C.LE  | C.NGT |
		 hi |-------|-------|-------|-------|-------|-------|-------|-------|
	*/
	private static final void initCop1SMap() {
	
		COP1_S_MAP.put( 0, UNHANDLED.getInstance());
		COP1_S_MAP.put( 1, UNHANDLED.getInstance());
		COP1_S_MAP.put( 2, UNHANDLED.getInstance());
		COP1_S_MAP.put( 3, UNHANDLED.getInstance());
		COP1_S_MAP.put( 4, UNHANDLED.getInstance());
		COP1_S_MAP.put( 5, UNHANDLED.getInstance());
		COP1_S_MAP.put( 6, UNHANDLED.getInstance());
		COP1_S_MAP.put( 7, UNHANDLED.getInstance());

		COP1_S_MAP.put( 8, UNHANDLED.getInstance());
		COP1_S_MAP.put( 9, UNHANDLED.getInstance());
		COP1_S_MAP.put(10, UNHANDLED.getInstance());
		COP1_S_MAP.put(11, UNHANDLED.getInstance());
		COP1_S_MAP.put(12, UNHANDLED.getInstance());
		COP1_S_MAP.put(13, UNHANDLED.getInstance());
		COP1_S_MAP.put(14, UNHANDLED.getInstance());
		COP1_S_MAP.put(15, UNHANDLED.getInstance());

		COP1_S_MAP.put(16, UNHANDLED.getInstance());
		COP1_S_MAP.put(17, UNHANDLED.getInstance());
		COP1_S_MAP.put(18, UNHANDLED.getInstance());
		COP1_S_MAP.put(19, UNHANDLED.getInstance());
		COP1_S_MAP.put(20, UNHANDLED.getInstance());
		COP1_S_MAP.put(21, UNHANDLED.getInstance());
		COP1_S_MAP.put(22, UNHANDLED.getInstance());
		COP1_S_MAP.put(23, UNHANDLED.getInstance());
		
		COP1_S_MAP.put(24, UNHANDLED.getInstance());
		COP1_S_MAP.put(25, UNHANDLED.getInstance());
		COP1_S_MAP.put(26, UNHANDLED.getInstance());
		COP1_S_MAP.put(27, UNHANDLED.getInstance());
		COP1_S_MAP.put(28, UNHANDLED.getInstance());
		COP1_S_MAP.put(29, UNHANDLED.getInstance());
		COP1_S_MAP.put(30, UNHANDLED.getInstance());
		COP1_S_MAP.put(31, UNHANDLED.getInstance());
		
		COP1_S_MAP.put(32, UNHANDLED.getInstance());
		COP1_S_MAP.put(33, UNHANDLED.getInstance());
		COP1_S_MAP.put(34, UNHANDLED.getInstance());
		COP1_S_MAP.put(35, UNHANDLED.getInstance());
		COP1_S_MAP.put(36, UNHANDLED.getInstance());
		COP1_S_MAP.put(37, UNHANDLED.getInstance());
		COP1_S_MAP.put(38, UNHANDLED.getInstance());
		COP1_S_MAP.put(39, UNHANDLED.getInstance());
		
		COP1_S_MAP.put(40, UNHANDLED.getInstance());
		COP1_S_MAP.put(41, UNHANDLED.getInstance());
		COP1_S_MAP.put(42, UNHANDLED.getInstance());
		COP1_S_MAP.put(43, UNHANDLED.getInstance());
		COP1_S_MAP.put(44, UNHANDLED.getInstance());
		COP1_S_MAP.put(45, UNHANDLED.getInstance());
		COP1_S_MAP.put(46, UNHANDLED.getInstance());
		COP1_S_MAP.put(47, UNHANDLED.getInstance());
		
		COP1_S_MAP.put(48, UNHANDLED.getInstance());
		COP1_S_MAP.put(49, UNHANDLED.getInstance());
		COP1_S_MAP.put(50, UNHANDLED.getInstance());
		COP1_S_MAP.put(51, UNHANDLED.getInstance());
		COP1_S_MAP.put(52, UNHANDLED.getInstance());
		COP1_S_MAP.put(53, UNHANDLED.getInstance());
		COP1_S_MAP.put(54, UNHANDLED.getInstance());
		COP1_S_MAP.put(55, UNHANDLED.getInstance());
		
		COP1_S_MAP.put(56, UNHANDLED.getInstance());
		COP1_S_MAP.put(57, UNHANDLED.getInstance());
		COP1_S_MAP.put(58, UNHANDLED.getInstance());
		COP1_S_MAP.put(59, UNHANDLED.getInstance());
		COP1_S_MAP.put(60, UNHANDLED.getInstance());
		COP1_S_MAP.put(61, UNHANDLED.getInstance());
		COP1_S_MAP.put(62, UNHANDLED.getInstance());
		COP1_S_MAP.put(63, UNHANDLED.getInstance());
	}
	
	/**
		    FPU: Instructions encoded by the function field when opcode = COP1
		         and fmt = D
		    31--------26-25------21 -------------------------------5--------0
		    |  = COP1   |  = D    |                               | function|
		    ------6----------5-----------------------------------------6-----
		    |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo
		000 | ADD   | SUB   | MUL   | DIV   | SQRT  | ABS   | MOV   | NEG   |
		001 |ROUND.L|TRUNC.L| CEIL.L|FLOOR.L|ROUND.W|TRUNC.W| CEIL.W|FLOOR.W|
		010 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		011 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		100 | CVT.S |  ---  |  ---  |  ---  | CVT.W | CVT.L |  ---  |  ---  |
		101 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		110 | C.F   | C.UN  | C.EQ  | C.UEQ | C.OLT | C.ULT | C.OLE | C.ULE |
		111 | C.SF  | C.NGLE| C.SEQ | C.NGL | C.LT  | C.NGE | C.LE  | C.NGT |
		 hi |-------|-------|-------|-------|-------|-------|-------|-------|
	*/
	private static final void initCop1DMap() {
		
		COP1_D_MAP.put( 0, UNHANDLED.getInstance());
		COP1_D_MAP.put( 1, UNHANDLED.getInstance());
		COP1_D_MAP.put( 2, UNHANDLED.getInstance());
		COP1_D_MAP.put( 3, UNHANDLED.getInstance());
		COP1_D_MAP.put( 4, UNHANDLED.getInstance());
		COP1_D_MAP.put( 5, UNHANDLED.getInstance());
		COP1_D_MAP.put( 6, UNHANDLED.getInstance());
		COP1_D_MAP.put( 7, UNHANDLED.getInstance());

		COP1_D_MAP.put( 8, UNHANDLED.getInstance());
		COP1_D_MAP.put( 9, UNHANDLED.getInstance());
		COP1_D_MAP.put(10, UNHANDLED.getInstance());
		COP1_D_MAP.put(11, UNHANDLED.getInstance());
		COP1_D_MAP.put(12, UNHANDLED.getInstance());
		COP1_D_MAP.put(13, UNHANDLED.getInstance());
		COP1_D_MAP.put(14, UNHANDLED.getInstance());
		COP1_D_MAP.put(15, UNHANDLED.getInstance());

		COP1_D_MAP.put(16, UNHANDLED.getInstance());
		COP1_D_MAP.put(17, UNHANDLED.getInstance());
		COP1_D_MAP.put(18, UNHANDLED.getInstance());
		COP1_D_MAP.put(19, UNHANDLED.getInstance());
		COP1_D_MAP.put(20, UNHANDLED.getInstance());
		COP1_D_MAP.put(21, UNHANDLED.getInstance());
		COP1_D_MAP.put(22, UNHANDLED.getInstance());
		COP1_D_MAP.put(23, UNHANDLED.getInstance());
		
		COP1_D_MAP.put(24, UNHANDLED.getInstance());
		COP1_D_MAP.put(25, UNHANDLED.getInstance());
		COP1_D_MAP.put(26, UNHANDLED.getInstance());
		COP1_D_MAP.put(27, UNHANDLED.getInstance());
		COP1_D_MAP.put(28, UNHANDLED.getInstance());
		COP1_D_MAP.put(29, UNHANDLED.getInstance());
		COP1_D_MAP.put(30, UNHANDLED.getInstance());
		COP1_D_MAP.put(31, UNHANDLED.getInstance());
		
		COP1_D_MAP.put(32, UNHANDLED.getInstance());
		COP1_D_MAP.put(33, UNHANDLED.getInstance());
		COP1_D_MAP.put(34, UNHANDLED.getInstance());
		COP1_D_MAP.put(35, UNHANDLED.getInstance());
		COP1_D_MAP.put(36, UNHANDLED.getInstance());
		COP1_D_MAP.put(37, UNHANDLED.getInstance());
		COP1_D_MAP.put(38, UNHANDLED.getInstance());
		COP1_D_MAP.put(39, UNHANDLED.getInstance());
		
		COP1_D_MAP.put(40, UNHANDLED.getInstance());
		COP1_D_MAP.put(41, UNHANDLED.getInstance());
		COP1_D_MAP.put(42, UNHANDLED.getInstance());
		COP1_D_MAP.put(43, UNHANDLED.getInstance());
		COP1_D_MAP.put(44, UNHANDLED.getInstance());
		COP1_D_MAP.put(45, UNHANDLED.getInstance());
		COP1_D_MAP.put(46, UNHANDLED.getInstance());
		COP1_D_MAP.put(47, UNHANDLED.getInstance());
		
		COP1_D_MAP.put(48, UNHANDLED.getInstance());
		COP1_D_MAP.put(49, UNHANDLED.getInstance());
		COP1_D_MAP.put(50, UNHANDLED.getInstance());
		COP1_D_MAP.put(51, UNHANDLED.getInstance());
		COP1_D_MAP.put(52, UNHANDLED.getInstance());
		COP1_D_MAP.put(53, UNHANDLED.getInstance());
		COP1_D_MAP.put(54, UNHANDLED.getInstance());
		COP1_D_MAP.put(55, UNHANDLED.getInstance());
		
		COP1_D_MAP.put(56, UNHANDLED.getInstance());
		COP1_D_MAP.put(57, UNHANDLED.getInstance());
		COP1_D_MAP.put(58, UNHANDLED.getInstance());
		COP1_D_MAP.put(59, UNHANDLED.getInstance());
		COP1_D_MAP.put(60, UNHANDLED.getInstance());
		COP1_D_MAP.put(61, UNHANDLED.getInstance());
		COP1_D_MAP.put(62, UNHANDLED.getInstance());
		COP1_D_MAP.put(63, UNHANDLED.getInstance());
	}
	
	/**
		    FPU: Instructions encoded by the function field when opcode = COP1
		         and fmt = W
		    31--------26-25------21 -------------------------------5--------0
		    |  = COP1   |  = W    |                               | function|
		    ------6----------5-----------------------------------------6-----
		    |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo
		000 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		001 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		010 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		011 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		100 | CVT.S | CVT.D |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		101 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		110 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		111 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		 hi |-------|-------|-------|-------|-------|-------|-------|-------|
	*/
	private static final void initCop1WMap() {
		
		COP1_W_MAP.put( 0, UNHANDLED.getInstance());
		COP1_W_MAP.put( 1, UNHANDLED.getInstance());
		COP1_W_MAP.put( 2, UNHANDLED.getInstance());
		COP1_W_MAP.put( 3, UNHANDLED.getInstance());
		COP1_W_MAP.put( 4, UNHANDLED.getInstance());
		COP1_W_MAP.put( 5, UNHANDLED.getInstance());
		COP1_W_MAP.put( 6, UNHANDLED.getInstance());
		COP1_W_MAP.put( 7, UNHANDLED.getInstance());

		COP1_W_MAP.put( 8, UNHANDLED.getInstance());
		COP1_W_MAP.put( 9, UNHANDLED.getInstance());
		COP1_W_MAP.put(10, UNHANDLED.getInstance());
		COP1_W_MAP.put(11, UNHANDLED.getInstance());
		COP1_W_MAP.put(12, UNHANDLED.getInstance());
		COP1_W_MAP.put(13, UNHANDLED.getInstance());
		COP1_W_MAP.put(14, UNHANDLED.getInstance());
		COP1_W_MAP.put(15, UNHANDLED.getInstance());

		COP1_W_MAP.put(16, UNHANDLED.getInstance());
		COP1_W_MAP.put(17, UNHANDLED.getInstance());
		COP1_W_MAP.put(18, UNHANDLED.getInstance());
		COP1_W_MAP.put(19, UNHANDLED.getInstance());
		COP1_W_MAP.put(20, UNHANDLED.getInstance());
		COP1_W_MAP.put(21, UNHANDLED.getInstance());
		COP1_W_MAP.put(22, UNHANDLED.getInstance());
		COP1_W_MAP.put(23, UNHANDLED.getInstance());
		
		COP1_W_MAP.put(24, UNHANDLED.getInstance());
		COP1_W_MAP.put(25, UNHANDLED.getInstance());
		COP1_W_MAP.put(26, UNHANDLED.getInstance());
		COP1_W_MAP.put(27, UNHANDLED.getInstance());
		COP1_W_MAP.put(28, UNHANDLED.getInstance());
		COP1_W_MAP.put(29, UNHANDLED.getInstance());
		COP1_W_MAP.put(30, UNHANDLED.getInstance());
		COP1_W_MAP.put(31, UNHANDLED.getInstance());
		
		COP1_W_MAP.put(32, UNHANDLED.getInstance());
		COP1_W_MAP.put(33, UNHANDLED.getInstance());
		COP1_W_MAP.put(34, UNHANDLED.getInstance());
		COP1_W_MAP.put(35, UNHANDLED.getInstance());
		COP1_W_MAP.put(36, UNHANDLED.getInstance());
		COP1_W_MAP.put(37, UNHANDLED.getInstance());
		COP1_W_MAP.put(38, UNHANDLED.getInstance());
		COP1_W_MAP.put(39, UNHANDLED.getInstance());
		
		COP1_W_MAP.put(40, UNHANDLED.getInstance());
		COP1_W_MAP.put(41, UNHANDLED.getInstance());
		COP1_W_MAP.put(42, UNHANDLED.getInstance());
		COP1_W_MAP.put(43, UNHANDLED.getInstance());
		COP1_W_MAP.put(44, UNHANDLED.getInstance());
		COP1_W_MAP.put(45, UNHANDLED.getInstance());
		COP1_W_MAP.put(46, UNHANDLED.getInstance());
		COP1_W_MAP.put(47, UNHANDLED.getInstance());
		
		COP1_W_MAP.put(48, UNHANDLED.getInstance());
		COP1_W_MAP.put(49, UNHANDLED.getInstance());
		COP1_W_MAP.put(50, UNHANDLED.getInstance());
		COP1_W_MAP.put(51, UNHANDLED.getInstance());
		COP1_W_MAP.put(52, UNHANDLED.getInstance());
		COP1_W_MAP.put(53, UNHANDLED.getInstance());
		COP1_W_MAP.put(54, UNHANDLED.getInstance());
		COP1_W_MAP.put(55, UNHANDLED.getInstance());
		
		COP1_W_MAP.put(56, UNHANDLED.getInstance());
		COP1_W_MAP.put(57, UNHANDLED.getInstance());
		COP1_W_MAP.put(58, UNHANDLED.getInstance());
		COP1_W_MAP.put(59, UNHANDLED.getInstance());
		COP1_W_MAP.put(60, UNHANDLED.getInstance());
		COP1_W_MAP.put(61, UNHANDLED.getInstance());
		COP1_W_MAP.put(62, UNHANDLED.getInstance());
		COP1_W_MAP.put(63, UNHANDLED.getInstance());
	}
	
	/**
		    FPU: Instructions encoded by the function field when opcode = COP1
		         and fmt = L
		    31--------26-25------21 -------------------------------5--------0
		    |  = COP1   |  = L    |                               | function|
		    ------6----------5-----------------------------------------6-----
		    |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo
		000 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		001 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		010 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		011 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		100 | CVT.S | CVT.D |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		101 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		110 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		111 |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |  ---  |
		 hi |-------|-------|-------|-------|-------|-------|-------|-------|
	*/
	private static final void initCop1LMap() {
	
		COP1_L_MAP.put( 0, UNHANDLED.getInstance());
		COP1_L_MAP.put( 1, UNHANDLED.getInstance());
		COP1_L_MAP.put( 2, UNHANDLED.getInstance());
		COP1_L_MAP.put( 3, UNHANDLED.getInstance());
		COP1_L_MAP.put( 4, UNHANDLED.getInstance());
		COP1_L_MAP.put( 5, UNHANDLED.getInstance());
		COP1_L_MAP.put( 6, UNHANDLED.getInstance());
		COP1_L_MAP.put( 7, UNHANDLED.getInstance());

		COP1_L_MAP.put( 8, UNHANDLED.getInstance());
		COP1_L_MAP.put( 9, UNHANDLED.getInstance());
		COP1_L_MAP.put(10, UNHANDLED.getInstance());
		COP1_L_MAP.put(11, UNHANDLED.getInstance());
		COP1_L_MAP.put(12, UNHANDLED.getInstance());
		COP1_L_MAP.put(13, UNHANDLED.getInstance());
		COP1_L_MAP.put(14, UNHANDLED.getInstance());
		COP1_L_MAP.put(15, UNHANDLED.getInstance());

		COP1_L_MAP.put(16, UNHANDLED.getInstance());
		COP1_L_MAP.put(17, UNHANDLED.getInstance());
		COP1_L_MAP.put(18, UNHANDLED.getInstance());
		COP1_L_MAP.put(19, UNHANDLED.getInstance());
		COP1_L_MAP.put(20, UNHANDLED.getInstance());
		COP1_L_MAP.put(21, UNHANDLED.getInstance());
		COP1_L_MAP.put(22, UNHANDLED.getInstance());
		COP1_L_MAP.put(23, UNHANDLED.getInstance());
		
		COP1_L_MAP.put(24, UNHANDLED.getInstance());
		COP1_L_MAP.put(25, UNHANDLED.getInstance());
		COP1_L_MAP.put(26, UNHANDLED.getInstance());
		COP1_L_MAP.put(27, UNHANDLED.getInstance());
		COP1_L_MAP.put(28, UNHANDLED.getInstance());
		COP1_L_MAP.put(29, UNHANDLED.getInstance());
		COP1_L_MAP.put(30, UNHANDLED.getInstance());
		COP1_L_MAP.put(31, UNHANDLED.getInstance());
		
		COP1_L_MAP.put(32, UNHANDLED.getInstance());
		COP1_L_MAP.put(33, UNHANDLED.getInstance());
		COP1_L_MAP.put(34, UNHANDLED.getInstance());
		COP1_L_MAP.put(35, UNHANDLED.getInstance());
		COP1_L_MAP.put(36, UNHANDLED.getInstance());
		COP1_L_MAP.put(37, UNHANDLED.getInstance());
		COP1_L_MAP.put(38, UNHANDLED.getInstance());
		COP1_L_MAP.put(39, UNHANDLED.getInstance());
		
		COP1_L_MAP.put(40, UNHANDLED.getInstance());
		COP1_L_MAP.put(41, UNHANDLED.getInstance());
		COP1_L_MAP.put(42, UNHANDLED.getInstance());
		COP1_L_MAP.put(43, UNHANDLED.getInstance());
		COP1_L_MAP.put(44, UNHANDLED.getInstance());
		COP1_L_MAP.put(45, UNHANDLED.getInstance());
		COP1_L_MAP.put(46, UNHANDLED.getInstance());
		COP1_L_MAP.put(47, UNHANDLED.getInstance());
		
		COP1_L_MAP.put(48, UNHANDLED.getInstance());
		COP1_L_MAP.put(49, UNHANDLED.getInstance());
		COP1_L_MAP.put(50, UNHANDLED.getInstance());
		COP1_L_MAP.put(51, UNHANDLED.getInstance());
		COP1_L_MAP.put(52, UNHANDLED.getInstance());
		COP1_L_MAP.put(53, UNHANDLED.getInstance());
		COP1_L_MAP.put(54, UNHANDLED.getInstance());
		COP1_L_MAP.put(55, UNHANDLED.getInstance());
		
		COP1_L_MAP.put(56, UNHANDLED.getInstance());
		COP1_L_MAP.put(57, UNHANDLED.getInstance());
		COP1_L_MAP.put(58, UNHANDLED.getInstance());
		COP1_L_MAP.put(59, UNHANDLED.getInstance());
		COP1_L_MAP.put(60, UNHANDLED.getInstance());
		COP1_L_MAP.put(61, UNHANDLED.getInstance());
		COP1_L_MAP.put(62, UNHANDLED.getInstance());
		COP1_L_MAP.put(63, UNHANDLED.getInstance());
	}
	
	/**
	 * instruction decoding
	 */
	
	/**
	 * 
	 * @param instruction
	 * @return
	 */
	public static final int FUNCTION(final int instruction) {
		return (instruction >>  0) & 0x0000003F;
	}

	/**
	 * 
	 * @param instruction
	 * @return
	 */
	public static final int ND(final int instruction) {
		return (instruction >> 17) & 0x00000001;
	}

	/**
	 * 
	 * @param instruction
	 * @return
	 */
	public static final int RD_FS(final int instruction) {
		return (instruction >> 11) & 0x0000001F;
	}
	
	/**
	 * 
	 * @param instruction
	 * @return
	 */
	public static final int RS_BASE_FMT(final int instruction) {
		return (instruction >> 21) & 0x0000001F;
	}

	/**
	 * 
	 * @param instruction
	 * @return
	 */
	public static final int RT_FT(final int instruction) {
		return (instruction >> 16) & 0x0000001F;
	}

	/**
	 * 
	 * @param instruction
	 * @return
	 */
	public static final int SA_FD(final int instruction) {
		return (instruction >>  6) & 0x0000001F;
	}

	/**
	 * 
	 * @param instruction
	 * @return
	 */
	public static final int TF(final int instruction) {
		return (instruction >> 16) & 0x00000001;
	}
	
	/**
	 * Sign-extends a signed half-word value stored in an <code>int</code>.
	 * @param halfword signed half-word value stored in an <code>int</code>
	 * @return sign-extended half-word value stored in an <code>int</code>
	 */
	public static final int signExtendH(final int halfword) {

		if ((halfword & 0x00008000) != 0) {
			return (halfword | 0xFFFF0000);
		}
		else {
			return halfword;
		}
	}

	/**
	 * Sign-extends a signed byte value stored in an <code>int</code>.
	 * @param bite signed byte value stored in an <code>int</code>
	 * @return sign-extended byte value stored in an <code>int</code>
	 */
	public static final int signExtendB(final int bite) {

		if((bite & 0x00000080) != 0) {
			return bite | 0xFFFFFF00;
		}
		else {
			return bite;
		}
	}

	/**
	 * Zero-extends a 32-bit word stored in an <code>int</code> and returns the value 
	 * as a <code>long</code>. 
	 * @param word 32-bit word stored as an <code>int</code>
	 * @return a <code>long</code> storing a 32-bit word, upper 32 bits set to <code>0</code>
	 */
	public static final long zeroExtendW(final int word) {
		return (word & 0x00000000FFFFFFFFL);
	}
	
	/**
	 * overload of zeroExtendW(int), just masks off high 32-bits, for use with integer instructions
	 * @param word
	 * @return
	 */
	public static final long zeroExtendW(final long word) {
		return (word & 0x00000000FFFFFFFFL);
	}
	
	/**
	 * Zero-extends a 16-bit half-word stored in an <code>int</code> and returns the value
	 * as an <code>int</code>.
	 * @param halfword 16-bit half-word value stored as an <code>int</code>
	 * @return an <code>int</code> storing a 16-bit half-word, upper 16 bits set to <code>0</code>
	 */
	public static final int zeroExtendH(final int halfword) {
		return (halfword & 0x0000FFFF);
	}
	
	/**
	 * Zero-extends an 8-bit byte stored in an <code>int</code> and returns the value as an <code>int</code>.
	 * @param bite 8-bit byte value stored as an <code>int</code>
	 * @return an <code>int</code> storing an 8-bit byte, upper 24 bits set to <code>0</code>
	 */
	public static final int zeroExtendB(final int bite) {
		return (bite & 0x000000FF);
	}	
	
	/**
	 * 
	 * @param instruction
	 * @return
	 */
	public static final Instruction getOpcode(final int instruction) {
		return OPCODE_MAP.get(instruction);
	}

	/**
	 * 
	 * @param specialKey
	 * @return
	 */
	public static final Instruction getSpecial(final int specialKey) {
		return SPECIAL_MAP.get(specialKey);
	}

	/**
	 * 
	 * @param regimmKey
	 * @return
	 */
	public static final Instruction getRegimm(final int regimmKey) {
		return REGIMM_MAP.get(regimmKey);
	}

	/**
	 * 
	 * @param cop0Key
	 * @return
	 */
	public static final Instruction getCop0(final int cop0Key) {
		return COP0_MAP.get(cop0Key);
	}

	/**
	 * 
	 * @param cop1Key
	 * @return
	 */
	public static final Instruction getCop1(final int cop1Key) {
		return COP1_MAP.get(cop1Key);
	}
	
	/**
	 * 
	 * @param cop1SKey
	 * @return
	 */
	public static final Instruction getCop1S(final int cop1SKey) {
		return COP1_S_MAP.get(cop1SKey);
	}
	
	/**
	 * 
	 * @param cop1DKey
	 * @return
	 */
	public static final Instruction getCop1D(final int cop1DKey) {
		return COP1_D_MAP.get(cop1DKey);
	}
	
	/**
	 * 
	 * @param cop1WKey
	 * @return
	 */
	public static final Instruction getCop1W(final int cop1WKey) {
		return COP1_W_MAP.get(cop1WKey);
	}
	
	/**
	 * 
	 * @param cop1LKey
	 * @return
	 */
	public static final Instruction getCop1L(final int cop1LKey) {
		return COP1_L_MAP.get(cop1LKey);
	}
	
	/**
	 * 
	 * @param tlbKey
	 * @return
	 */
	public static final Instruction getTlb(final int tlbKey) {
		return TLB_MAP.get(tlbKey);
	}

	/**
	 * 
	 * @param bc1Key
	 * @return
	 */
	public static final Instruction getBc1(final int bc1Key) {
		return BC1_MAP.get(bc1Key);
	}
	
	/**
	 * 
	 * @param instruction
	 * @throws Exception
	 */
	public static void dispatch(final int instruction) throws Exception {
		OPCODE_MAP.get((instruction >> 26) &  0x0000003F).execute(instruction);
	}
	
	/**
	 * The following four methods should be over-ridden in every subclass of Instruction,
	 * but due to author laziness, project won't build if they are abstract at the moment. 
	 */
	
	/**
	 * @param instruction the instruction to be decoded and executed
	 * @throws BreakpointException 
	 */
	public void execute(final int instruction) throws Exception {
		throw new mips.exceptions.UnimplementedInstructionException(mips.R4300i.PC,instruction);
	}

	/**
	 * Returns a <code>String</code> representation of the Java code executed during a call of the <code>execute()</code> method for use in the 
	 * basic-block emitter.<br/>The emitted code does not contain logging or tracing instrumentation code.
	 * @param instruction the instruction to be decoded and emitted
	 * @return a <code>String</code> containing code close to the contents of the <code>execute()</code> method for this instruction class.
	 */
	public String emit(final int instruction) {
		return "Emit not implemented for instruction: " + this.getName();
	}
	
	/**
	 * Get a <code>String</code> representation of the name of the given instruction.<br/>
	 * This may differ from the actual name of the class for several types of instructions<br/>
	 * that need further decoding before dispatching by various opcode or function fields.<br/>
	 * @return a <code>String</code> representing the instruction name
	 */
	public String getName(final int instruction) {
		return Instruction.getOpcode((instruction >> 26) &  0x0000003F).getName();
	}
	
	/**
	 * Get a <code>String</code> representation of the name of the instruction this object represents.
	 * @return a <code>String</code> representing the instruction name
	 */
	public abstract String getName();
}
